#ifndef NANE_WINAPI_H
#   define NANE_WINAPI_H

// support Windows 98 and later
#   ifndef WINVER
#       define WINVER 0x0410
#   endif

#   ifndef _WIN32_WINDOWS               // Allow use of features specific to Windows 98 or later.
#       define _WIN32_WINDOWS 0x0410    // WIN98
#   endif

#   define WIN32_LEAN_AND_MEAN
#   include <Windows.h>
#   undef CreateFile
#   undef GetFileAttributes
#   undef DeleteFile
#   undef CreateDirectory
#   undef RemoveDirectory
#   undef CreateWindow
#   undef CreateWindowA
#   undef CreateWindowW
#   undef GetCommandLine
#   undef RegisterClass
#   undef PeekMessage
#   undef DispatchMessage
#   undef DefWindowProc
#   undef SetWindowLongPtr
#   undef GetWindowLongPtr
#   undef CallWindowProc

#   include <string>

#   include "nane/core/types.h"

#   define NANE_WINAPI_FUNCTION( ret, func, params, args )\
static ret func##A params;\
static ret func##W params;\
static ret func params\
{\
return SupportUnicode() ? func##W args : func##A args;\
}

namespace nane
{

    class WinAPI
    {
    public:
        static bool SupportUnicode();
        static void Utf8ToWstr( const char* _utf8, wchar_t* _wstr, uint32 _wstrSize );
        static void Utf8ToWstr( const std::string& _utf8, std::wstring* _wstr );
        static void WstrToUtf8( const std::wstring& _wstr, std::string* _utf8 );
        static void AnsiToWstr( const std::string& _ansi, std::wstring* _wstr );
        static void WstrToAnsi( const wchar_t* _wstr, char* _ansi, uint32 _ansiSize );
        static void WstrToAnsi( const std::wstring& _wstr, std::string* _ansi );
        static void Utf8ToAnsi( const char* _utf8, char* _ansi, uint32 _ansiSize );
        static void Utf8ToAnsi( const std::string& _utf8, std::string* _ansi );
        static void AnsiToUtf8( const std::string& _ansi, std::string* _utf8 );
        NANE_WINAPI_FUNCTION( HANDLE, CreateFile,
                             ( const std::string& _lpFileName, DWORD _dwDesiredAccess
                             , DWORD _dwShareMode, LPSECURITY_ATTRIBUTES _lpSecurityAttributes
                             , DWORD _dwCreationDisposition, DWORD _dwFlagsAndAttributes
                             , HANDLE _hTemplateFile )
                           , (_lpFileName,_dwDesiredAccess, _dwShareMode, _lpSecurityAttributes
                             , _dwCreationDisposition, _dwFlagsAndAttributes, _hTemplateFile ) );
        NANE_WINAPI_FUNCTION( DWORD, GetFileAttributes, ( const std::string& _filename ), (_filename) );
        NANE_WINAPI_FUNCTION( BOOL, DeleteFile, ( const std::string& _filename ), (_filename) );
        NANE_WINAPI_FUNCTION( BOOL, CreateDirectory
             , ( const std::string& _directoryPath, LPSECURITY_ATTRIBUTES _securityAttributes )
             , (_directoryPath, _securityAttributes) );
        NANE_WINAPI_FUNCTION( BOOL, RemoveDirectory
                                 , ( const std::string& _directoryPath )
                                 , (_directoryPath) );
        NANE_WINAPI_FUNCTION( HWND, CreateWindow
                                 , ( const char* _className, const char* _windowName
                                   , DWORD _style, int _x, int _y, int _width, int _height
                                   , HWND _hWndParent, HMENU _hMenu, HINSTANCE _hInstance
                                   , LPVOID _param )
                                , (_className, _windowName, _style, _x, _y, _width, _height
                                   , _hWndParent, _hMenu, _hInstance, _param) );
        NANE_WINAPI_FUNCTION( void, GetCommandLine, ( std::string* _commandLine ), (_commandLine) );
        NANE_WINAPI_FUNCTION( ATOM, RegisterClass, ( const char* _className, HINSTANCE _hInstance, WNDPROC _wndProc )
                                                 , (_className, _hInstance, _wndProc) );
        static BOOL UnregisterClass( ATOM _classAtom, HINSTANCE _hInstance );
        NANE_WINAPI_FUNCTION( HWND, CreateWindow
                                 , ( ATOM _classAtom, const char* _windowName, DWORD _style
                                  , int _x, int _y, int _width, int _height, HWND _hWndParent
                                  , HMENU _hMenu, HINSTANCE _hInstance, void* _param )
                              , (_classAtom, _windowName, _style, _x, _y, _width, _height
                                 , _hWndParent, _hMenu, _hInstance, _param) );
        NANE_WINAPI_FUNCTION( BOOL, PeekMessage, ( LPMSG _msg, HWND _hWnd, UINT _msgFilterMin, UINT _msgFilterMax, UINT _removeMsg )
                                                                                   , (_msg, _hWnd, _msgFilterMin, _msgFilterMax, _removeMsg) );
        NANE_WINAPI_FUNCTION( LRESULT, DispatchMessage, ( const MSG* _msg ), (_msg) );
        NANE_WINAPI_FUNCTION( LRESULT, DefWindowProc, ( HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam )
                                                                                                , (_hWnd, _msg, _wParam, _lParam) );
        NANE_WINAPI_FUNCTION( LONG_PTR, SetWindowLongPtr, ( HWND _hWnd, int _index, LONG_PTR _newLong )
                                                                                                        , (_hWnd, _index, _newLong) );
        NANE_WINAPI_FUNCTION( LONG_PTR, GetWindowLongPtr, ( HWND _hWnd, int _index ), (_hWnd, _index) );
        NANE_WINAPI_FUNCTION( LRESULT, CallWindowProc, ( WNDPROC _wndProc, HWND _hWnd, UINT _msg, WPARAM _wParam, LPARAM _lParam ), (_wndProc, _hWnd, _msg, _wParam, _lParam) );

	};

}   // namespace nane

#   undef NANE_WINAPI_FUNCTION

#endif  // NANE_WINAPI_H
